/*
 *  Copyright 2011-2012 Redia A/S
 * 
 *  This file is part of Redias Android Utilities.
 *
 *  Redias Android Utilities is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Redias Android Utilities is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with Redias Android Utilities.  If not, see <http://www.gnu.org/licenses/>.
 */
package dk.redia.lib.model;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import dk.redia.lib.log.Log;
import dk.redia.lib.xmlrpc.XmlRpcResultUtils;

public class Channel {
/*
 * 10-28 10:47:06.560: I/System.out(3380):   channelId: 
10-28 10:47:06.570: I/System.out(3380):     bahjf
10-28 10:47:06.570: I/System.out(3380):   channelNames: 
10-28 10:47:06.570: I/System.out(3380):     {
10-28 10:47:06.570: I/System.out(3380):     dk: 
10-28 10:47:06.570: I/System.out(3380):       Mobile Arrangementer
10-28 10:47:06.570: I/System.out(3380):     ,
10-28 10:47:06.570: I/System.out(3380):     }
10-28 10:47:06.570: I/System.out(3380):   customerId: 
10-28 10:47:06.570: I/System.out(3380):     koebenhavnsbib
10-28 10:47:06.570: I/System.out(3380):   ,
10-28 10:47:06.570: I/System.out(3380):   }
10-28 10:47:06.570: I/System.out(3380): ,

 */
	
	private static final String logTag = "Channel";
	
	private static final int NEXT_TEXT_NONE = 0;
	private static final int NEXT_TEXT_INFOOBJECT_ID = 1;
	private static final int NEXT_TEXT_CHANNEL_NAME = 2;
	private static final int NEXT_TEXT_ID = 3;
	private static final int NEXT_TEXT_CUSTOMER_ID = 4;
	
	private String id;
	private Map<String, String> names;
	private String customerId;
	private Map<AbsoluteId, InfoObject> infoObjects;
	private Object[] ordering;
	
	private Channel() {
		names = new HashMap<String, String>();
		infoObjects = new HashMap<AbsoluteId, InfoObject>();
	}
	
	public static Channel fromMap(Map<String, Object> map) {
		if (!map.containsKey("channelId")) {
			Log.e(logTag, "Channel map missing chanelId key");
			return null;
		}
		if (!map.containsKey("channelNames")) {
			Log.e(logTag, "Channel map missing channelNames key");
		}
		if (!map.containsKey("customerId")) {
			Log.e(logTag, "Channel map missing customerId key");
			return null;
		}
		if (!map.containsKey("infoObjects")) {
			Log.e(logTag, "Channel map missing infoObjects key");
		}
		if(!map.containsKey("ordering")) {
			Log.e(logTag, "Channel map missing ordering key");
		}
		Channel c = new Channel();
		
		try {
			c.setId((String)map.get("channelId"));
			c.setCustomerId((String)map.get("customerId"));
			Map<String, Object> channelNames = XmlRpcResultUtils.unpackStruct(map.get("channelNames"));
			if (channelNames!=null) {
				c.setNames(new HashMap<String, String>());
				for (String key : channelNames.keySet()) {
					String name = (String)channelNames.get(key);
					c.names.put(key, name);
				}
			} else {
				Log.e(logTag, "Unable to convert channelNames to map");
			}
		
		} catch (ClassCastException e) {
			return null;
		}
		return c;
		
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getCustomerId() {
		return customerId;
	}

	public void setCustomerId(String customerId) {
		this.customerId = customerId;
	}

	public Map<String, String> getNames() {
		return names;
	}

	public void setNames(Map<String, String> names) {
		this.names = names;
	}
	
	public Object[] getOrdering() {
		return ordering;
	}
	
	public void setOrdering(Object[] array) {
		ordering = array;
	}
	
	public String getXml() {
		StringBuilder sb = new StringBuilder();
		sb.append("<channel>");
		sb.append("<id>" + this.id + "</id>");
		sb.append("<customer-id>" + this.customerId + "</customer-id>");
		sb.append("<names>");
		for (String language : this.names.keySet()) {
			sb.append("<name language=\"" + language + "\">" + names.get(language) + "</name>");
		}
		for (AbsoluteId id : this.infoObjects.keySet()) {
			sb.append("<infoobject-id>" + id.toString() + "</infoobject-id>");
		}
		sb.append("</names>");
		sb.append("</channel>");
		return sb.toString();
	}

	public void addInfoObject(InfoObject io) {
		Log.d(Channel.logTag, "Adding info object with absolute id hashcode " + io.getAbsoluteId().hashCode() + " to map");
		Log.d(Channel.logTag, "Absolute id is: " + io.getAbsoluteId().toString());
		Log.d(Channel.logTag, "Info object list size before put: " + this.infoObjects.size());
		this.infoObjects.put(io.getAbsoluteId(), io);
		Log.d(Channel.logTag, "Info object list size after put: " + this.infoObjects.size());
	}

	public AbsoluteId getAbsouteId() {
		return new AbsoluteId(this.customerId, this.id);
	}

	public void removeAllInfoObjects() {
		this.infoObjects.clear();
	}

	public Map<AbsoluteId, InfoObject> getInfoObjects() {
		return this.infoObjects;
	}

	/**
	 * Get a shallow Channel instance. Ie. one that is not populated with info object objects
	 * 
	 * @param xml
	 * @return
	 */
	public static Channel fromXml(String xml) {
		try {
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
	        factory.setNamespaceAware(false);
	        XmlPullParser xpp = factory.newPullParser();
	        xpp.setInput(new StringReader (xml));
	        Channel c = new Channel();
	        String language = "";
	        int eventType;
	        int nextText = NEXT_TEXT_NONE;
	        while ((eventType = xpp.getEventType())!=XmlPullParser.END_DOCUMENT) {
	        	switch (eventType) {
	        	case XmlPullParser.START_TAG:
	        		if (xpp.getName().equals("name")) {
	        			language = xpp.getAttributeValue(null, "language");
	        			nextText = NEXT_TEXT_CHANNEL_NAME;
	        		} else if (xpp.getName().equals("infoobject-id")) {
	        			nextText = NEXT_TEXT_INFOOBJECT_ID;
	        		} else if (xpp.getName().equals("id")) {
	        			nextText = NEXT_TEXT_ID;
	        		} else if (xpp.getName().equals("customer-id")) {
	        			nextText = NEXT_TEXT_CUSTOMER_ID;
	        		}
	        		break;
	        	case XmlPullParser.TEXT:
	        		String text = xpp.getText();
	        		switch (nextText) {
	        		case NEXT_TEXT_CHANNEL_NAME:
	        			Log.d(Channel.logTag, "Setting channel name to " + text + " for language " + language + " during load from XML");
	        			c.names.put(language, xpp.getText());
	        			break;
	        		case NEXT_TEXT_INFOOBJECT_ID:
//	        			if (!shallow) {
//		        			AbsoluteId ioid = new AbsoluteId(text);
//		        			InfoObject io = InfoGalleriModel.getInstance().loadInfoObject(ioid);
//		        			if (io!=null) {
//		        				c.infoObjects.put(ioid, io);
//		        			}
//	        			}
	        			break;
	            	case NEXT_TEXT_ID:
		        		c.id = text;
		        		break;
		        	case NEXT_TEXT_CUSTOMER_ID:
		        		c.customerId = text;
		        		break;

	        		}
	        	}
	        	xpp.next();
	        }
	        return c;
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
}
